// Package mgmt
// @Author: zhengqi Wu
// @Description:
// @Version: 1.0.0
// @Date: 2021/3/10 11:01 上午
// @Copyright: MIN-Group；国家重大科技基础设施——未来网络北大实验室；深圳市信息论与未来网络重点实验室
//

const ControlResponseCodeSuccess = 200
const ControlResponseCodeContinue = 201
const ControlResponseCodeCommonError = 400

const ControlResponseTypeString = "string"
const ControlResponseTypeMeta = "meta"
const ControlResponseTypeBytes = "bytes"

class ControlResponse {
    constructor() {
        this.code = 0;
        this.type = "";
        this.msg = "";
        this.data = "";
    }

    /**
     * GetString data为字符串，按字符串类型访问 Data
     * @returns {string}
     */
    getString(){
        if (this.type === ControlResponseTypeString)
            return this.data
        throw new Error(`Wrong type of data: ${typeof(this.data)}`)
    }

    /**
     * SetString 按字符串类型设置 Data
     * @param str
     */
    setString(str){
        this.type = ControlResponseTypeString
        this.data = str
    }

    /**
     * GetMeta data为元数据，按元数据类型访问 Data
     * @returns {string}
     */
    getMeta(){
        if (this.type === ControlResponseTypeMeta)
            return this.data
        throw new Error(`Wrong type of data: ${typeof(this.data)}`)
    }

    /**
     * SetMeta 按元数据类型设置 Data
     * @param str
     */
    setMeta(meta){
        this.type = ControlResponseTypeMeta
        this.data = meta
    }

    /**
     * GetBytes 按字节数组类型获取 Data
     * @returns {string}
     */
    getBytes(){
        if (this.type === ControlResponseTypeBytes)
            return this.data
        throw new Error(`Wrong type of data: ${typeof(this.data)}`)
    }

    /**
     * SetBytes 按字节数组类型设置 Data
     * @param bytes
     */
    setBytes(bytes){
        this.type = ControlResponseTypeBytes
        this.data = bytes
    }

    /**
     * @description UnmarshalJSON 自定义 JSON 反序列化逻辑，可以根据不同类型，Data 反序列化为对应的子类型
     * @param bytes
     */
    unmarshalJSON(bytes){
        let jsonString = String(bytes)
        let obj = JSON.parse(jsonString) // 先获取json对象
        // 反序列化基本属性
        this.code = obj['Code']
        this.type = obj['Type']
        this.msg = obj['Msg']
        // 反序列化data
        let data = obj['Data']
        switch (this.type){
            case ControlResponseTypeString:
            case ControlResponseTypeBytes:
                // string 与 bytes 一样都是直接赋值
                this.data = data
                break
            case ControlResponseTypeMeta:
                // 从data对象中提取属性
                let meta = new ControlResponseMeta()
                meta.sliceNum = BigInt(data['SliceNum'])
                meta.version = BigInt(data['Version'])
                this.data = meta
                break
            default:
                throw new Error(`Non support type: ${this.type}`)
        }
    }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////
///// Meta 定义
/////////////////////////////////////////////////////////////////////////////////////////////////////////

/**
 * ControlResponseMeta 表示一个管理控制命令的元数据结构
 */
class ControlResponseMeta{
    constructor() {
        this.version = BigInt(0)
        this.sliceNum = BigInt(0)
    }
}

/**
 * CreateMetaDataControlResponse 创建一个表示元数据的返回响应
 * @param version
 * @param sliceNum
 * @returns {ControlResponse}
 */
function createMetaDataControlResponse(version, sliceNum){
    let response = new ControlResponse()
    response.code = ControlResponseCodeContinue
    let meta = new ControlResponseMeta()
    meta.version = version
    meta.sliceNum = sliceNum
    response.setMeta(meta)
    return response
}

module.exports = {
    ControlResponseMeta: ControlResponseMeta,
    ControlResponse: ControlResponse,
    createMetaDataControlResponse: createMetaDataControlResponse,
    ControlResponseCodeSuccess: ControlResponseCodeSuccess,
    ControlResponseCodeContinue: ControlResponseCodeContinue,
    ControlResponseCodeCommonError: ControlResponseCodeCommonError,
    ControlResponseTypeString: ControlResponseTypeString,
    ControlResponseTypeMeta: ControlResponseTypeMeta,
    ControlResponseTypeBytes: ControlResponseTypeBytes
}